import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { useProblemsStore, type ProblemItem, type ProblemSeverity } from '../stores/problems';
import { useWorkspaceStore } from '../stores/workspace';
import { workspaceIndexer } from './WorkspaceIndexer.ts';
import { v4 as uuid } from 'uuid';
import { invoke } from '@tauri-apps/api/core';
import { ref, computed } from 'vue';

// 诊断扫描状态
export interface DiagnosticScanProgress {
  phase: 'idle' | 'discovering' | 'analyzing' | 'complete' | 'error';
  currentFile: string;
  processedFiles: number;
  totalFiles: number;
  startTime?: number;
  endTime?: number;
  error?: string;
}

/**
 * 工作区诊断服务 - 实现类似VS Code的工作区范围问题检测
 * 设计思路：
 * 1. 分层架构：UI层 -> 诊断服务层 -> 语言分析层
 * 2. 推送模式：主动分析文件并推送诊断信息
 * 3. 缓存机制：避免重复分析同一文件
 * 4. 增量更新：只更新变化的文件
 */
export class WorkspaceDiagnosticService {
  private static _instance: WorkspaceDiagnosticService | null = null;
  private _problems: any = null;
  
  // 文件诊断缓存：文件路径 -> 诊断结果
  private diagnosticsCache = new Map<string, ProblemItem[]>();
  
  // 文件修改时间缓存：文件路径 -> 修改时间
  private fileModTimeCache = new Map<string, number>();
  
  // 正在分析的文件集合，避免重复分析
  private analyzingFiles = new Set<string>();
  
  // 支持的文件扩展名
  private supportedExtensions = new Set([
    '.ts', '.tsx', '.js', '.jsx', '.vue', '.json',
    '.html', '.css', '.scss', '.md', '.yaml', '.yml'
  ]);

  // 进度状态管理
  private _progress = ref<DiagnosticScanProgress>({
    phase: 'idle',
    currentFile: '',
    processedFiles: 0,
    totalFiles: 0
  });

  private _isScanning = ref(false);

  // 取消控制
  private _abortController: AbortController | null = null;

  // 公开的响应式属性
  get progress() { return this._progress; }
  get isScanning() { return this._isScanning; }

  // 计算属性：扫描完成百分比
  get progressPercent() {
    return computed(() => {
      const { processedFiles, totalFiles } = this._progress.value;
      if (totalFiles === 0) return 0;
      return Math.round((processedFiles / totalFiles) * 100);
    });
  }

  // 计算属性：预估剩余时间
  get estimatedTimeRemaining() {
    return computed(() => {
      const { phase, processedFiles, totalFiles, startTime } = this._progress.value;
      if (phase !== 'analyzing') return null;
      if (!startTime || processedFiles === 0) return null;
      
      const elapsed = Date.now() - startTime;
      const avgTimePerFile = elapsed / processedFiles;
      const remaining = totalFiles - processedFiles;
      
      return Math.round((remaining * avgTimePerFile) / 1000); // 返回秒数
    });
  }

  // 懒加载获取problems store
  private get problems() {
    if (!this._problems) {
      try {
        this._problems = useProblemsStore();
      } catch (error) {
        console.warn('Problems store not available yet, will retry later');
        return null;
      }
    }
    return this._problems;
  }

  static get instance(): WorkspaceDiagnosticService {
    if (!this._instance) {
      this._instance = new WorkspaceDiagnosticService();
    }
    return this._instance;
  }

  constructor() {
    this.initializeService();
  }

  /**
   * 初始化服务
   */
  private async initializeService() {
    // 监听工作区文件变化
    this.setupFileWatchers();
    
    // 初始扫描工作区
    await this.performInitialScan();
  }

  /**
   * 设置文件监听器
   */
  private setupFileWatchers() {
    // 利用现有的watcher系统
    // 监听工作区文件变化
    const workspaceStore = useWorkspaceStore();
    if (workspaceStore.workspaceRoot) {
      // 注册文件系统事件监听
      this.setupFileSystemListener();
    }
  }

  /**
   * 设置文件系统事件监听
   */
  private async setupFileSystemListener() {
    try {
      const { listen } = await import('@tauri-apps/api/event');
      
      // 监听文件系统事件
      await listen('file_changed', (event: any) => {
        const { path, event_type } = event.payload;
        
        if (this.isAnalyzableFile(path)) {
          switch (event_type) {
            case 'Write':
            case 'Create':
              // 文件修改或创建，重新分析
              this.analyzeFileManually(path);
              break;
            case 'Remove':
              // 文件删除，清除诊断信息
              this.clearFileDiagnostics(path);
              break;
          }
        }
      });
    } catch (error) {
      console.warn('Failed to setup file system listener:', error);
    }
  }

  /**
   * 检查文件是否可分析
   */
  private isAnalyzableFile(filePath: string): boolean {
    const ext = this.getFileExtension(filePath);
    return this.supportedExtensions.has(ext);
  }

  /**
   * 执行初始工作区扫描
   */
  private async performInitialScan() {
    if (this._isScanning.value) {
      console.warn('Diagnostic scan already in progress, skipping duplicate request');
      return;
    }

    this._isScanning.value = true;
    this._abortController = new AbortController();
    
    console.log('[WorkspaceDiagnosticService] Starting workspace diagnostic scan...');

    try {
      const workspaceStore = useWorkspaceStore();
      let scanRoot = workspaceStore.workspaceRoot;
      
      // 如果工作区根目录为空，使用当前项目目录作为回退
      if (!scanRoot) {
        const fallbackPath = 'c:\\Users\\24648\\Desktop\\tauri\\tauri-angular';
        console.log(`No workspace root found, using fallback path: ${fallbackPath}`);
        scanRoot = fallbackPath;
        
        // 尝试设置工作区根目录以便后续使用
        try {
          await workspaceStore.setWorkspaceRoot(scanRoot);
          console.log(`Workspace root set to: ${scanRoot}`);
        } catch (error) {
          console.warn('Failed to set workspace root:', error);
        }
      }
      
      if (!scanRoot) {
        console.log('No workspace root available, skipping initial scan');
        return;
      }

      // 初始化进度
      this._progress.value = {
        phase: 'discovering',
        currentFile: '等待工作区索引完成...',
        processedFiles: 0,
        totalFiles: 0,
        startTime: Date.now()
      };

      console.log(`Starting workspace diagnostic scan using indexer for: ${scanRoot}`);
      
      // 等待工作区索引器完成，避免并发冲突
      await this.waitForIndexerCompletion(scanRoot);
      
      // 利用工作区索引器获取文件列表
      const files = await this.discoverFilesFromIndex(scanRoot);
      
      if (this._abortController?.signal.aborted) {
        throw new Error('Scan cancelled');
      }

      // 更新总文件数
      this._progress.value.totalFiles = files.length;
      this._progress.value.phase = 'analyzing';
      this._progress.value.currentFile = '开始分析代码问题...';
      
      // 批量分析文件（限制并发数量）
      await this.analyzeFilesInBatches(files, 5);

      // 完成
      this._progress.value.phase = 'complete';
      this._progress.value.endTime = Date.now();
      
      console.log(`Workspace diagnostic scan completed. Analyzed ${files.length} files.`);
    } catch (error) {
      console.error('Failed to perform initial workspace scan:', error);
      this._progress.value.phase = 'error';
      this._progress.value.error = String(error);
    } finally {
      this._isScanning.value = false;
      this._abortController = null;
    }
  }

  /**
   * 等待工作区索引器完成
   */
  private async waitForIndexerCompletion(rootPath: string): Promise<void> {
    const maxWaitTime = 60000; // 增加到60秒
    const startTime = Date.now();
    
    // 如果索引器正在运行，等待它完成
    while (workspaceIndexer.isIndexing.value && (Date.now() - startTime) < maxWaitTime) {
      this._progress.value.currentFile = `等待工作区索引完成... (${Math.floor((Date.now() - startTime) / 1000)}s)`;
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      if (this._abortController?.signal.aborted) {
        throw new Error('Diagnostic scan cancelled');
      }
    }
    
    // 如果索引器没有在运行且目录没有被索引，等待一下或者启动索引
    if (!workspaceIndexer.isIndexing.value && !workspaceIndexer.isDirectoryIndexed(rootPath)) {
      console.log('Workspace not indexed, waiting a bit more for auto-indexing...');
      // 再等待5秒，给自动索引时间
      await new Promise(resolve => setTimeout(resolve, 5000));
      
      // 如果还是没有索引，就继续使用回退方法
      if (!workspaceIndexer.isDirectoryIndexed(rootPath)) {
        console.log('Workspace still not indexed, diagnostic service will use fallback method');
      }
    }
  }

  /**
   * 利用工作区索引器发现文件
   */
  private async discoverFilesFromIndex(rootPath: string): Promise<string[]> {
    try {
      // 检查工作区索引器是否已经完成索引
      if (!workspaceIndexer.isDirectoryIndexed(rootPath)) {
        console.log('Workspace not indexed, falling back to search API');
        return this.discoverWorkspaceFiles(rootPath);
      }
      
      // 从索引中递归收集所有文件
      const files: string[] = [];
      const visitedDirs = new Set<string>();
      
      const collectFilesFromIndex = (dirPath: string) => {
        const normalizedPath = this.normalizePath(dirPath);
        if (visitedDirs.has(normalizedPath)) return;
        visitedDirs.add(normalizedPath);
        
        const children = workspaceIndexer.getIndexedChildren(dirPath);
        if (!children) return;
        
        for (const child of children) {
          if (child.isDir) {
            // 递归处理子目录
            collectFilesFromIndex(child.id);
          } else {
            // 检查文件是否可分析
            if (this.isAnalyzableFile(child.id)) {
              files.push(child.id);
            }
          }
        }
      };
      
      collectFilesFromIndex(rootPath);
      
      console.log(`Discovered ${files.length} analyzable files from workspace index`);
      return files;
      
    } catch (error) {
      console.warn('Failed to discover files from index, falling back to search API:', error);
      // 回退到原有的方法
      return this.discoverWorkspaceFiles(rootPath);
    }
  }

  /**
   * 发现工作区中的所有相关文件（回退方法）
   */
  private async discoverWorkspaceFiles(rootPath: string): Promise<string[]> {
    try {
      // 使用现有的search API获取文件列表
      const supportedExts = Array.from(this.supportedExtensions).join(',');
      const searchResult = await invoke<any[]>('search_files', {
        directory: rootPath,
        pattern: '*', // 匹配所有文件
        include_pattern: `*{${supportedExts}}`, // 只包含支持的扩展名
        exclude_pattern: 'node_modules/**,dist/**,build/**,.git/**,coverage/**,target/**,out/**',
        max_results: 10000 // 设置一个较大的限制
      });
      
      return searchResult.map(item => item.path).filter(Boolean);
    } catch (error) {
      console.error('Failed to discover workspace files:', error);
      return [];
    }
  }

  /**
   * 批量分析文件
   */
  private async analyzeFilesInBatches(files: string[], batchSize: number) {
    for (let i = 0; i < files.length; i += batchSize) {
      const batch = files.slice(i, i + batchSize);
      const promises = batch.map(file => this.analyzeFile(file));
      
      await Promise.allSettled(promises);
      
      // 每批次之间稍作停顿，避免资源占用过高
      await new Promise(resolve => setTimeout(resolve, 10));
    }
  }

  /**
   * 分析单个文件
   */
  private async analyzeFile(filePath: string): Promise<void> {
    if (this.analyzingFiles.has(filePath)) {
      return; // 避免重复分析
    }

    if (this._abortController?.signal.aborted) {
      throw new Error('Analysis cancelled');
    }

    this.analyzingFiles.add(filePath);

    try {
      // 更新进度
      this._progress.value.currentFile = this.getRelativePath(filePath);
      
      // 检查文件是否需要重新分析
      const shouldAnalyze = await this.shouldAnalyzeFile(filePath);
      if (!shouldAnalyze) {
        return;
      }

      // 读取文件内容
      const content = await invoke<string>('fs_read_text', { path: filePath });
      
      // 创建临时Monaco模型进行分析
      const diagnostics = await this.analyzeFileContent(filePath, content);
      
      // 更新缓存
      this.diagnosticsCache.set(filePath, diagnostics);
      
      // 使用实际文件修改时间而不是当前时间
      try {
        const stats = await invoke<{ modified_ms: number }>('fs_stat', { path: filePath });
        this.fileModTimeCache.set(filePath, stats.modified_ms);
      } catch {
        this.fileModTimeCache.set(filePath, Date.now());
      }
      
      // 更新进度计数
      this._progress.value.processedFiles++;
      
      // 更新问题存储
      this.updateProblemsStore();

    } catch (error) {
      console.warn(`Failed to analyze file ${filePath}:`, error);
    } finally {
      this.analyzingFiles.delete(filePath);
    }
  }

  /**
   * 检查文件是否需要重新分析
   */
  private async shouldAnalyzeFile(filePath: string): Promise<boolean> {
    try {
      // 获取文件修改时间
      const stats = await invoke<{ modified_ms: number }>('fs_stat', { path: filePath });
      const lastModified = stats.modified_ms;
      
      // 检查缓存中的修改时间
      const cachedModTime = this.fileModTimeCache.get(filePath);
      
      return !cachedModTime || lastModified > cachedModTime;
    } catch {
      // 如果无法获取文件信息，默认需要分析
      return true;
    }
  }

  /**
   * 分析文件内容
   */
  private async analyzeFileContent(filePath: string, content: string): Promise<ProblemItem[]> {
    const problems: ProblemItem[] = [];
    
    try {
      // 获取文件扩展名
      const ext = this.getFileExtension(filePath);
      const language = this.getLanguageFromExtension(ext);
      
      // 创建临时Monaco模型
      const uri = monaco.Uri.file(filePath);
      
      // 检查是否已存在模型，避免重复创建
      let model = monaco.editor.getModel(uri);
      const isTemporary = !model;
      
      if (!model) {
        try {
          model = monaco.editor.createModel(content, language, uri);
        } catch (error) {
          console.warn(`Failed to create Monaco model for ${filePath}:`, error);
          return problems;
        }
      }

      // 等待语言服务分析完成
      await this.waitForLanguageAnalysis();
      
      // 获取诊断信息，添加错误处理
      let markers: monaco.editor.IMarker[] = [];
      try {
        markers = monaco.editor.getModelMarkers({ resource: uri });
      } catch (error) {
        console.warn(`Failed to get markers for ${filePath}:`, error);
        // 如果获取标记失败，继续处理下一个文件
        if (isTemporary && model) {
          try {
            model.dispose();
          } catch (disposeError) {
            console.warn(`Failed to dispose model for ${filePath}:`, disposeError);
          }
        }
        return problems;
      }
      
      // 转换为问题格式，只收集错误和警告
      markers.forEach(marker => {
        try {
          const severity = this.convertSeverity(marker.severity);
          // 只记录错误和警告，过滤掉信息级别的问题
          if (severity === 'error' || severity === 'warning') {
            problems.push({
              id: uuid(),
              severity,
              message: marker.message,
              file: this.getRelativePath(filePath),
              line: marker.startLineNumber,
              column: marker.startColumn,
            });
          }
        } catch (markerError) {
          console.warn(`Failed to process marker for ${filePath}:`, markerError);
        }
      });

      // 清理临时模型
      if (isTemporary && model) {
        try {
          model.dispose();
        } catch (disposeError) {
          console.warn(`Failed to dispose temporary model for ${filePath}:`, disposeError);
        }
      }

    } catch (error) {
      console.warn(`Failed to analyze content for ${filePath}:`, error);
    }

    return problems;
  }

  /**
   * 等待语言服务分析完成
   */
  private async waitForLanguageAnalysis(timeout = 1000): Promise<void> {
    return new Promise((resolve) => {
      // 简单的延迟等待，实际项目中可能需要更复杂的机制
      setTimeout(resolve, timeout);
    });
  }

  /**
   * 更新问题存储
   */
  private updateProblemsStore() {
    const allProblems: ProblemItem[] = [];
    
    // 合并所有文件的诊断信息
    for (const diagnostics of this.diagnosticsCache.values()) {
      allProblems.push(...diagnostics);
    }

    // 同时包含Monaco编辑器的实时诊断
    const monacoProblems = this.getMonacoProblems();
    
    // 去重：优先使用Monaco的实时诊断
    const mergedProblems = this.mergeProblems(allProblems, monacoProblems);

    // 更新存储
    const problemsStore = this.problems;
    if (problemsStore) {
      problemsStore.set(mergedProblems);
    }
  }

  /**
   * 获取Monaco编辑器的实时诊断
   */
  private getMonacoProblems(): ProblemItem[] {
    const problems: ProblemItem[] = [];
    
    try {
      monaco.editor.getModels().forEach(model => {
        try {
          const markers = monaco.editor.getModelMarkers({ resource: model.uri });
          
          markers.forEach(marker => {
            try {
              const severity = this.convertSeverity(marker.severity);
              // 只记录错误和警告，过滤掉信息级别的问题
              if (severity === 'error' || severity === 'warning') {
                problems.push({
                  id: uuid(),
                  severity,
                  message: marker.message,
                  file: this.getRelativePath(model.uri.fsPath),
                  line: marker.startLineNumber,
                  column: marker.startColumn,
                });
              }
            } catch (markerError) {
              console.warn(`Failed to process Monaco marker:`, markerError);
            }
          });
        } catch (modelError) {
          console.warn(`Failed to get markers for model:`, modelError);
        }
      });
    } catch (error) {
      console.warn('Failed to get Monaco problems:', error);
    }

    return problems;
  }

  /**
   * 合并问题列表，Monaco诊断优先
   */
  private mergeProblems(workspaceProblems: ProblemItem[], monacoProblems: ProblemItem[]): ProblemItem[] {
    const monacoFiles = new Set(monacoProblems.map(p => p.file));
    
    // 过滤掉已在Monaco中打开的文件的工作区诊断
    const filteredWorkspaceProblems = workspaceProblems.filter(p => !monacoFiles.has(p.file));
    
    return [...monacoProblems, ...filteredWorkspaceProblems];
  }

  /**
   * 手动触发文件分析
   */
  async analyzeFileManually(filePath: string): Promise<void> {
    await this.analyzeFile(filePath);
  }

  /**
   * 手动触发完整工作区扫描
   */
  async startFullScan(): Promise<void> {
    if (this._isScanning.value) {
      console.log('[WorkspaceDiagnosticService] Scan already in progress, ignoring duplicate request');
      return;
    }
    
    await this.performInitialScan();
  }

  /**
   * 取消正在进行的扫描
   */
  cancelScan(): void {
    if (this._abortController) {
      this._abortController.abort();
    }
  }

  /**
   * 清除文件的诊断信息
   */
  clearFileDiagnostics(filePath: string): void {
    this.diagnosticsCache.delete(filePath);
    this.fileModTimeCache.delete(filePath);
    this.updateProblemsStore();
  }

  /**
   * 获取工作区诊断统计信息
   */
  getWorkspaceDiagnosticsStats() {
    const totalFiles = this.diagnosticsCache.size;
    let totalProblems = 0;
    let errorCount = 0;
    let warningCount = 0;
    let infoCount = 0;

    for (const diagnostics of this.diagnosticsCache.values()) {
      totalProblems += diagnostics.length;
      
      for (const problem of diagnostics) {
        switch (problem.severity) {
          case 'error': errorCount++; break;
          case 'warning': warningCount++; break;
          case 'info': infoCount++; break;
        }
      }
    }

    return {
      totalFiles,
      totalProblems,
      errorCount,
      warningCount,
      infoCount
    };
  }

  // 辅助方法
  private convertSeverity(severity: monaco.MarkerSeverity): ProblemSeverity {
    switch (severity) {
      case monaco.MarkerSeverity.Error: return 'error';
      case monaco.MarkerSeverity.Warning: return 'warning';
      case monaco.MarkerSeverity.Info: return 'info';
      default: return 'info';
    }
  }

  private getFileExtension(filePath: string): string {
    const lastDot = filePath.lastIndexOf('.');
    return lastDot > 0 ? filePath.substring(lastDot) : '';
  }

  private getLanguageFromExtension(ext: string): string {
    switch (ext.toLowerCase()) {
      case '.js': case '.jsx': return 'javascript';
      case '.ts': case '.tsx': return 'typescript';
      case '.vue': return 'html'; // Vue文件按HTML处理
      case '.json': return 'json';
      case '.css': case '.scss': return 'css';
      case '.html': return 'html';
      case '.md': return 'markdown';
      case '.yaml': case '.yml': return 'yaml';
      default: return 'plaintext';
    }
  }

  private getRelativePath(filePath: string): string {
    const workspaceStore = useWorkspaceStore();
    if (workspaceStore.workspaceRoot && filePath.startsWith(workspaceStore.workspaceRoot)) {
      return filePath.substring(workspaceStore.workspaceRoot.length + 1);
    }
    return filePath;
  }

  /**
   * 路径规范化（与工作区索引器保持一致）
   */
  private normalizePath(path: string): string {
    let s = String(path || '').replace(/\\/g, '/');
    if (s.length > 3) s = s.replace(/\/+$/g, '');
    if (/^[a-zA-Z]:\//.test(s)) s = s.toLowerCase();
    return s;
  }

  /**
   * 清理服务
   */
  dispose() {
    this.diagnosticsCache.clear();
    this.fileModTimeCache.clear();
    this.analyzingFiles.clear();
    WorkspaceDiagnosticService._instance = null;
  }
}

// 导出获取单例实例的函数
export const getWorkspaceDiagnosticService = () => WorkspaceDiagnosticService.instance;